package com.ruben.simplescaffold.utils;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Opt;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruben.simplescaffold.entity.UserDetail;
import com.ruben.simplescaffold.enumration.RoleEnum;
import com.ruben.simplescaffold.exception.UserNotFoundException;

import java.time.LocalDateTime;
import java.util.function.Supplier;

/**
 * 用户工具类
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/8/25 12:10
 */
public class UserUtils {

    public static final ThreadLocal<UserDetail> USER_THREAD = new InheritableThreadLocal<>();

    private UserUtils() {
        /* Do not new me! */
    }

    /**
     * 没登录
     */
    public static final Supplier<UserNotFoundException> NOT_LOGIN = () -> new UserNotFoundException("not login");
    /**
     * 用户sessionKey
     */
    public static final String USER_SESSION_KEY = "USER";

    /**
     * 登录，返回token
     *
     * @param userDetail 用户信息
     * @return java.lang.String
     * @author <achao1441470436@gmail.com>
     * @since 2021/8/25 17:04
     */
    public static String userLogin(UserDetail userDetail) {
        // 登录
        StpUtil.login(userDetail.getId());
        // 存储用户信息
        StpUtil.getSession().set(USER_SESSION_KEY, userDetail);
        // 返回token
        return StpUtil.getTokenValue();
    }

    /**
     * 获取用户信息
     *
     * @return cn.hutool.core.lang.Opt<com.ruben.simplescaffold.entity.UserDetail>
     * @author <achao1441470436@gmail.com>
     * @since 2021/9/9 10:33
     */
    public static Opt<UserDetail> getUser() {
        return Opt.ofNullable(USER_THREAD.get()).or(() -> UserUtils.getUserIdOpt().map(StpUtil::getSessionByLoginId).map(s -> s.get(USER_SESSION_KEY)).map(u -> (JSONObject) u).map(u -> u.toJavaObject(UserDetail.class)));
    }

    /**
     * 获取用户编号
     *
     * @return java.lang.Long
     * @throws UserNotFoundException 未获取到抛出
     * @author <achao1441470436@gmail.com>
     * @since 2021/8/25 12:11
     */
    public static Long getUserId() {
        return getUserIdOpt().orElseThrow(NOT_LOGIN);
    }

    /**
     * 获取用户编号，有可能获取不到
     *
     * @return cn.hutool.core.lang.Opt<java.lang.Long>
     * @author <achao1441470436@gmail.com>
     * @since 2021/10/5 11:20
     */
    public static Opt<Long> getUserIdOpt() {
        return Opt.ofNullable(StpUtil.getLoginIdDefaultNull()).map(id -> Long.valueOf((String) id));
    }

    /**
     * 通过loginName查询用户
     *
     * @param userDetail 用户参数
     * @return cn.hutool.core.lang.Opt<com.ruben.xchat.entity.UserDetail>
     * @author <achao1441470436@gmail.com>
     * @since 2021/8/26 9:59
     */
    public static Opt<UserDetail> getUserByUsername(UserDetail userDetail) {
        return Opt.ofNullable(userDetail.getUsername()).map(loginName -> UserDetail.builder().username(loginName).build()).map(Wrappers::lambdaQuery).map(userDetail::selectOne);
    }

    /**
     * 获取注册时间
     *
     * @return cn.hutool.core.date.DateTime
     * @throws UserNotFoundException 未获取到抛出
     * @author <achao1441470436@gmail.com>
     * @since 2021/9/6 15:36
     */
    public static LocalDateTime getRegisterTime() {
        return getUser().map(UserDetail::getGmtCreate).orElseThrow(NOT_LOGIN);
    }

    /**
     * 设置当前用户
     *
     * @param userDetail 用户信息
     * @author <achao1441470436@gmail.com>
     * @since 2021/9/10 16:23
     */
    public static void setUser(UserDetail userDetail) {
        USER_THREAD.set(userDetail);
    }

    /**
     * 获取用户租户id
     *
     * @return Opt
     * @author <achao1441470436@gmail.com>
     * @since 2021/9/9 10:40
     */
    public static Opt<Long> getTenantId() {
        return getUser().map(UserDetail::getTenantId);
    }

    /**
     * 当前用户是否包含某角色
     *
     * @param roleTypeEnum 角色
     * @return java.lang.Boolean
     * @author <achao1441470436@gmail.com>
     * @since 2021/9/9 11:13
     */
    public static Boolean checkRole(RoleEnum roleTypeEnum) {
        return StpUtil.hasRole(roleTypeEnum.name());
    }

    /**
     * 当前用户是否不包含某角色或未登录
     *
     * @param roleTypeEnum 角色
     * @return boolean
     * @author <achao1441470436@gmail.com>
     * @since 2021/9/9 11:17
     */
    public static boolean hasNoRole(RoleEnum roleTypeEnum) {
        return !checkRole(roleTypeEnum);
    }

    /**
     * 移除当前用户
     *
     * @author <achao1441470436@gmail.com>
     * @since 2021/10/22 16:49
     */
    public static void clear() {
        USER_THREAD.remove();
    }


}
